home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1986-01-22 | 7.4 KB | 262 lines |
- IMPLEMENTATION MODULE Parser;
- (* Reads the Source file, and splits each *)
- (* line into Label, OpCode & Operand(s). *)
-
- FROM FileSystem IMPORT
- File, ReadChar;
-
- FROM ErrorX68 IMPORT
- ErrorType, Error;
-
- IMPORT ASCII;
-
-
- (*---
- (* These objects are declared in the DEFINITION MODULE *)
- CONST
- TokenSize = 8;
- OperandSize = 20;
-
- TYPE
- TOKEN = ARRAY [0..TokenSize] OF CHAR;
- OPERAND = ARRAY [0..OperandSize] OF CHAR;
- STRING = ARRAY [0..80] OF CHAR;
-
- VAR
- OpLoc, SrcLoc, DestLoc : CARDINAL; (* location of line parts *)
- Line : STRING;
- LineCount : CARDINAL;
- ---*)
-
-
- PROCEDURE GetLine (VAR f : File; VAR EndFile : BOOLEAN);
- (* Inputs a Line -- up to 80 characters ending in cr/lf -- from a file. *)
-
- CONST
- MAXLINE = 80;
-
- VAR
- i : CARDINAL;
- ch : CHAR;
-
- BEGIN
- i := 0;
- LOOP
- IF f.eof THEN
- EndFile := TRUE;
- EXIT;
- END;
- ReadChar (f, ch);
-
- IF (ch = ASCII.EOL) OR (i >= MAXLINE) THEN
- EXIT;
- END;
-
- Line[i] := ch;
- INC (i);
- END;
-
- Line[i] := 0C; (* null terminate line *)
- INC (LineCount);
- END GetLine;
-
-
-
- PROCEDURE SplitLine (VAR Label, OpCode : TOKEN;
- VAR SrcOp, DestOp : OPERAND);
- (* Separates TOKENs & OPERANDs from Line. *)
-
- CONST
- Quote = 47C;
- StringMAX = 12;
-
- VAR
- i, j : CARDINAL;
- ParCnt : INTEGER; (* Tracks open parentheses *)
- c : CHAR;
- InQuotes : BOOLEAN;
-
- PROCEDURE Cap (ch : CHAR) : CHAR;
- BEGIN
- IF InQuotes THEN
- RETURN (ch);
- ELSE
- RETURN CAP (ch);
- END;
- END Cap;
-
- PROCEDURE White (ch : CHAR) : BOOLEAN;
- BEGIN
- RETURN ((ch = ASCII.ht) OR (ch = ' '));
- END White;
-
- PROCEDURE Delimiter (ch : CHAR) : BOOLEAN;
- BEGIN
- RETURN (((ch = ' ') AND (NOT InQuotes))
- OR (ch = ASCII.ht) OR (ch = 0C));
- END Delimiter;
-
- PROCEDURE OpDelimiter (ch : CHAR) : BOOLEAN;
- BEGIN
- RETURN ((ch = ',') AND (NOT InQuotes) AND (ParCnt = 0));
- END OpDelimiter;
-
- PROCEDURE Done (ch : CHAR) : BOOLEAN;
- (* look for start of comment or NULL terminator *)
- BEGIN
- RETURN ((ch = ';') OR (ch = 0C) OR ((ch = '*') AND (i = 0)));
- END Done;
-
-
- BEGIN (* SplitLine *)
- i := 0;
- InQuotes := FALSE;
-
- IF Done (Line[i]) THEN (* look for blank or all-comment line *)
- RETURN;
- END;
-
- IF White (Line[i]) THEN
- INC (i);
- WHILE White (Line[i]) DO
- INC (i); (* Skip spaces & tabs *)
- END;
- ELSE (* Found a Label *)
- j := 0;
- c := Line[i];
- WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
- Label[j] := CAP (c);
- INC (i); INC (j);
- c := Line[i];
- END;
- Label[j] := 0C; (* terminate Label string *)
- IF j = TokenSize THEN
- Error (i, TooLong);
- END;
- WHILE NOT Delimiter (Line[i]) DO
- INC (i); (* Skip remainder of Too-Long Token *)
- END;
- END;
-
- WHILE White (Line[i]) DO
- INC (i);
- END;
-
- IF Done (Line[i]) THEN
- RETURN;
- ELSE (* Found an OpCode *)
- OpLoc := i;
- j := 0;
- c := Line[i];
- WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
- OpCode[j] := CAP (c);
- INC (i); INC (j);
- c := Line[i];
- END;
- OpCode[j] := 0C;
- IF j = TokenSize THEN
- Error (i, TooLong);
- END;
- WHILE NOT Delimiter (Line[i]) DO
- INC (i); (* Skip remainder of Too-Long Token *)
- END;
- END;
-
- WHILE White (Line[i]) DO
- INC (i);
- END;
-
- IF Done (Line[i]) THEN
- RETURN;
- ELSE (* Found 1st Operand *)
- SrcLoc := i;
- j := 0;
- ParCnt := 0;
- c := Line[i];
- IF c = Quote THEN (* String Constant *)
- SrcOp[j] := c;
- INC (i); INC (j);
- REPEAT
- c := Line[i];
- SrcOp[j] := c;
- INC (i); INC (j);
- UNTIL (c = Quote) OR (j > StringMAX) OR (c = 0C);
- SrcOp[j] := 0C;
- IF j > StringMAX THEN
- Error (i, TooLong);
- END;
- RETURN; (* second operand not allowed after string constant *)
- ELSE (* Normal Operand *)
- WHILE (NOT Delimiter (c))
- AND (NOT OpDelimiter (c))
- AND (j < OperandSize) DO
- IF c = Quote THEN
- InQuotes := NOT InQuotes; (* Toggle Switch *)
- END;
- IF NOT InQuotes THEN
- IF c = '(' THEN
- INC (ParCnt);
- END;
- IF c = ')' THEN
- DEC (ParCnt);
- END;
- END;
- SrcOp[j] := Cap (c); (* Switched CAP function *)
- INC (i); INC (j);
- c := Line[i];
- END;
- SrcOp[j] := 0C;
- IF j = OperandSize THEN
- Error (i, TooLong);
- END;
- END;
- WHILE (NOT Delimiter (Line[i])) AND (NOT OpDelimiter (Line[i])) DO
- INC (i); (* Skip remainder of Too-Long Operand *)
- END;
- END;
-
- IF NOT OpDelimiter (Line[i]) THEN
- RETURN; (* because only one OPERAND *)
- ELSE (* Found 2nd Operand *)
- INC (i); (* Skip OpDelimiter (comma) *)
- DestLoc := i;
- j := 0;
- c := Line[i];
- WHILE (NOT Delimiter (c)) AND (j < OperandSize) DO
- DestOp[j] := CAP (c);
- INC (i); INC (j);
- c := Line[i];
- END;
- DestOp[j] := 0C;
- IF j = OperandSize THEN
- Error (i, TooLong);
- END;
- END;
- END SplitLine;
-
-
-
- PROCEDURE LineParts (VAR f : File; VAR EndFile : BOOLEAN;
- VAR Label, OpCode : TOKEN;
- VAR SrcOp, DestOp : OPERAND);
- (* Reads line, breaks into tokens, on-passes to symbol & code generators *)
-
- BEGIN
- Line := "";
- GetLine (f, EndFile); (* read a line from the file *)
-
- IF EndFile THEN
- Error (0, EndErr);
- ELSE
- Label := ""; OpCode := ""; SrcOp := ""; DestOp := "";
- SplitLine (Label, OpCode, SrcOp, DestOp);
- END;
- END LineParts;
-
-
-
- BEGIN (* MODULE Initialization *)
- OpLoc := 0; SrcLoc := 0; DestLoc := 0; LineCount := 0;
- END Parser.
-